/**
 * RedisInstance 类提供了静态方法来管理和操作 Redis 数据库实例。
 * 它使用 ioredis 库来与 Redis 通信。
 *
 * @class RedisInstance
 */
import Redis from 'ioredis';
import redisConfig from '../config/redis.config';
const redisIndex = []; // 用于记录 Redis 实例索引
const redisList = []; // 用于存储 Redis 实例
const redisOption = {
  host: redisConfig.host,
  port: redisConfig.port,
};

/**
 * 初始化 Redis 实例。如果对应数据库尚未创建，则创建并缓存。
 *
 * @static
 * @param {string} method - 方法标识，用于日志或其他用途
 * @param {number} [db=0] - Redis 数据库编号，默认为 0
 * @returns {Redis} 返回对应的 Redis 实例
 */
export class RedisInstance {
  static async initRedis(method: string, db = 0) {
    const isExist = redisIndex.some((x) => x === db);
    if (!isExist) {
      redisList[db] = new Redis({ ...redisOption, db });
      redisIndex.push(db);
    }
    return redisList[db];
  }

  /**
   * 设置 Redis 键值对。如果值为对象，将先转换为 JSON 字符串。
   *
   * @static
   * @param {string} method - 方法标识，用于日志或其他用途
   * @param {number} [db=0] - Redis 数据库编号，默认为 0
   * @param {string} key - Redis 键
   * @param {string | object} val - Redis 的值，可以是字符串或对象
   * @param {number} [timeout=60*60] - 键的过期时间（秒，默认 1 小时）
   * @returns {Promise<void>} 操作成功无返回值，出错时抛出异常
   */
  static async setRedis(
    method: string,
    db = 0,
    key: string,
    val: string | object,
    timeout = 60 * 60,
  ) {
    if (typeof val === 'object') {
      val = JSON.stringify(val);
    }
    const redis = await RedisInstance.initRedis(method, db);
    redis.set(`${key}`, val);
    redis.expire(`${key}`, timeout);
  }

  /**
   * 获取 Redis 中的键值。
   *
   * @static
   * @param {string} method - 方法标识，用于日志或其他用途
   * @param {number} [db=0] - Redis 数据库编号，默认为 0
   * @param {string} key - Redis 键
   * @returns {Promise<string>} 返回键对应的值，出错时抛出异常
   */
  static async getRedis(method: string, db = 0, key: string) {
    return new Promise(async (resolve, reject) => {
      const redis = await RedisInstance.initRedis(method, db);
      redis.get(`${key}`, (err, val) => {
        if (err) {
          reject(err);
          return;
        }
        resolve(val);
      });
    });
  }
}
